﻿using System;
using SystemArray = System.Array;
using Map;
using Microsoft.Xna.Framework;

namespace Map_Creator.MapInfo
{
    public class AutoTile5 : AutoTile5Struct
    {
        public int[] CornerValues = new int[4];

        public override short Value
        {
            get
            {
                // allways return -1 since its too complex =]
                return -1;
            }
        }

            /************************************\
             * quarters are orderd like this    *
             *                                  *  
             * |-------|                        *
             * | 0 | 1 |                        *
             * |-------|                        *
             * | 2 | 3 |                        *
             * |-------|                        *
             *                                  *  
             * values are always clockwise      *  
             * by corners flags when the        *
             * corners are allways the last bit *
             *                                  *
             * all quarters are 3 bits          *
             * quarter 0 orderd as:             *
             * |LeftUp|Left|Up|                 *
             * quarter 1 orderd as:             *
             * |RightUp|Up|Right|               *
             * quarter 2 orderd as:             *
             * |LeftDown|Down|Left|             *
             * quarter 3 orderd as:             *
             * |RightDown|Right|Down|             *
            \************************************/

            public static int[,] Quarters = new[,]
                                  {
                                      {0,3,1,5,4  ,4,4,4},
                                      {1,0,4,5,3  ,3,3,3},
                                      {3,4,0,5,1  ,1,1,1},
                                      {4,1,3,5,0  ,0,0,0}
                                  };
        /*
            quarters[0, 0] = tiles[0]; //None
            quarters[1, 0] = tiles[1]; //None
            quarters[2, 0] = tiles[3]; //None
            quarters[3, 0] = tiles[4]; //None

            quarters[0, 1] = tiles[3]; //Up
            quarters[1, 1] = tiles[0]; //Left
            quarters[2, 1] = tiles[4]; //Right
            quarters[3, 1] = tiles[2]; //Down

            quarters[0, 2] = tiles[1]; //Right
            quarters[1, 2] = tiles[4]; //Up
            quarters[2, 2] = tiles[0]; //Down
            quarters[3, 2] = tiles[3]; //Left

            quarters[0, 3] = tiles[5]; //Up + Right
            quarters[1, 3] = tiles[5]; //Left + Up
            quarters[2, 3] = tiles[5]; //Right + Down
            quarters[3, 3] = tiles[5]; //Down + Left

            quarters[0, 4] = tiles[4]; //UpRight
            quarters[1, 4] = tiles[3]; //LeftUp
            quarters[2, 4] = tiles[1]; //RightDown
            quarters[3, 4] = tiles[0]; //DownLeft
        */

        public AutoTile5(AutoTileData aData)
        {
            if (aData.Type != AutoTileType.AutoTile5)
                throw new Exception("Bad AutoTileData Type");
            AutoData = aData;
            TileSetIndex = aData[0].TileSetIndex;
            Type = TileType.AutoDP;
        }

        public override void DrawTile(Microsoft.Xna.Framework.Graphics.SpriteBatch batch, MapStruct map, Rectangle destRect, Color color)
        {
            var tileSet = map.TileSets[TileSetIndex];
            var tileSize = map.TileSize;
            var halfSize = tileSize / 2;
            var destQuarterRect = new Rectangle(destRect.X, destRect.Y, halfSize, halfSize);
            batch.Draw(tileSet.TilesImage,
                     destQuarterRect,
                     new Rectangle((CornerValues[0] % tileSet.TilesSize.X) * tileSize,
                                      (CornerValues[0] / tileSet.TilesSize.X) * tileSize,
                                      halfSize, halfSize), color);
            destQuarterRect.X += halfSize;
            batch.Draw(tileSet.TilesImage,
                     destQuarterRect,
                     new Rectangle((CornerValues[1] % tileSet.TilesSize.X) * tileSize + halfSize,
                                      (CornerValues[1] / tileSet.TilesSize.X) * tileSize,
                                      halfSize, halfSize), color);
            destQuarterRect.Y += halfSize;

            batch.Draw(tileSet.TilesImage,
                       destQuarterRect,
                       new Rectangle((CornerValues[3]%tileSet.TilesSize.X)*tileSize + halfSize,
                                     (CornerValues[3]/tileSet.TilesSize.X)*tileSize + halfSize,
                                     halfSize, halfSize), color);
            destQuarterRect.X -= halfSize;
            batch.Draw(tileSet.TilesImage,
                       destQuarterRect,
                       new Rectangle((CornerValues[2]%tileSet.TilesSize.X)*tileSize,
                                     (CornerValues[2]/tileSet.TilesSize.X)*tileSize + halfSize,
                                     halfSize, halfSize), color);

        }

        public override void UpdateValue(TileStructGrid grid, Point pos, bool Recurse = true)
        {
            AutoTile5Corners newCorners = 0;

            var left = pos.X == 0;
            var right = pos.X == grid.Size.X - 1;
            var top = pos.Y == 0;
            var buttom = pos.Y == grid.Size.Y - 1;

            if (!left)
            {
                var aTile = grid[pos.X - 1, pos.Y];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.Left;
            }
            if (!right)
            {
                var aTile = grid[pos.X + 1, pos.Y];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.Right;
            }
            if (!top)
            {
                var aTile = grid[pos.X, pos.Y - 1];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.Up;
            }
            if (!buttom)
            {
                var aTile = grid[pos.X, pos.Y + 1];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.Down;
            }

            if (newCorners.HasFlag(AutoTile5Corners.Right) &&
                newCorners.HasFlag(AutoTile5Corners.Up))
            {
                var aTile = grid[pos.X + 1, pos.Y - 1];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.UpRight;
            }
            if (newCorners.HasFlag(AutoTile5Corners.Left) &&
                newCorners.HasFlag(AutoTile5Corners.Up))
            {
                var aTile = grid[pos.X - 1, pos.Y - 1];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.UpLeft;
            }
            if (newCorners.HasFlag(AutoTile5Corners.Right) &&
                newCorners.HasFlag(AutoTile5Corners.Down))
            {
                var aTile = grid[pos.X + 1, pos.Y + 1];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.DownRight;
            }
            if (newCorners.HasFlag(AutoTile5Corners.Left) &&
                newCorners.HasFlag(AutoTile5Corners.Down))
            {
                var aTile = grid[pos.X - 1, pos.Y + 1];
                if (aTile != null && aTile.Type == TileType.AutoDP && ((AutoTile5)aTile).AutoData == AutoData)
                    newCorners |= AutoTile5Corners.DownLeft;
            }

            if (Corners != newCorners)
            {
                Corners = newCorners;

                var corners = new int[4];
                var cornersAsInt = (int) Corners;
                corners[0] = (cornersAsInt & 7);
                corners[1] = (((cornersAsInt) >> 3) & 7);
                corners[2] = (((cornersAsInt) >> 6) & 7);
                corners[3] = (((cornersAsInt) >> 9) & 7);

                CornerValues[0] = AutoData[Quarters[0, corners[0]]].Value;
                CornerValues[1] = AutoData[Quarters[1, corners[1]]].Value;
                CornerValues[2] = AutoData[Quarters[2, corners[2]]].Value;
                CornerValues[3] = AutoData[Quarters[3, corners[3]]].Value;
            }
            base.UpdateValue(grid, pos, Recurse);
        }
    }
}